package cn.lingyangwl.agile.log;

import cn.lingyangwl.agile.log.enums.*;
import cn.lingyangwl.framework.core.response.*;
import cn.lingyangwl.framework.log.annotation.*;
import cn.lingyangwl.framework.log.common.*;
import cn.lingyangwl.framework.tool.core.*;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Objects;
import java.util.Optional;

/**
 * @author shenguangyang
 */
@Slf4j
@Configuration
public class CustomAccessLogConfig {
    @Bean
    public AccessLogConfig accessLogConfig() {
        return AccessLogConfig.builder()
            .defaultOprType(OperatorType.OTHER)
            .defaultBizType(BusinessType.OTHER)
            .logCallback((info) -> {
                AccessLog logAnnot = info.getLogAnnot();
                Boolean isPrintIn = Optional.ofNullable(logAnnot).map(AccessLog::isPrintIn).orElse(true);
                Boolean isPrintOut = Optional.ofNullable(logAnnot).map(AccessLog::isPrintOut).orElse(true);
                Object reqData = info.getReqData();
                Object respData = info.getRespData();
                String errorMsg = info.getErrorMsg();

                StringBuilder printfInfo = new StringBuilder();
                printfInfo.append("url: ").append(info.getUrl()).append(", ");
                printfInfo.append("method: ").append(info.getHttpMethod()).append(", ");
                if (StringUtils.isNotEmpty(errorMsg)) {
                    errorMsg = errorMsg.length() > 1000 ? errorMsg.substring(0, 1000) + " ......" : errorMsg;
                    info.setErrorMsg(errorMsg);
                    printfInfo.append("error: ").append(errorMsg).append(", ");
                }

                if (isPrintIn && Objects.nonNull(reqData)) {
                    String reqDataStr = JSON.toJSONString(reqData);
                    reqDataStr = reqDataStr.length() > 2000 ? reqDataStr.substring(0, 2000) + " ......" : reqDataStr;
                    info.setReqData(reqDataStr);
                    printfInfo.append("req: ").append(reqDataStr).append(", ");
                }

                Object printfRespData = respData instanceof Resp ? ((Resp<?>) respData).getData() : respData;

                if (isPrintOut && Objects.nonNull(printfRespData)) {
                    String respDataStr = JSON.toJSONString(printfRespData);
                    respDataStr = respDataStr.length() > 2000 ? respDataStr.substring(0, 2000) + " ......" : respDataStr;
                    info.setRespData(respDataStr);
                    printfInfo.append("resp: ").append(respDataStr).append(", ");
                }
                int index = printfInfo.lastIndexOf(",");
                if (info.getStatus() == BizStatus.OK) {
                    log.info("request-{}", printfInfo.substring(0, index));
                } else {
                    log.error("request-{}", printfInfo.substring(0, index));
                }
            }).build();
    }
}
